home *** CD-ROM | disk | FTP | other *** search
/ Power Programmierung 2 / Power-Programmierung CD 2 (Tewi)(1994).iso / gnu / gnulib / fchart / flblarr.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-06-05  |  16.5 KB  |  661 lines

  1. /*
  2.  *
  3.  *  Fchart  --  flblarr.c
  4.  *
  5.  *  Copyright (C) 1990 Piotr Filip Sawicki
  6.  *
  7.  * Permission to use, copy, and distribute this software and its
  8.  * documentation for any purpose with or without fee is hereby granted,
  9.  * provided that the above copyright notice appear in all copies and
  10.  * that both that copyright notice and this permission notice appear
  11.  * in supporting documentation.
  12.  *
  13.  * Permission to modify the software is granted, but not the right to
  14.  * distribute the modified code.  Modifications are to be distributed
  15.  * as patches to released version.
  16.  *
  17.  *  Please e-mail any useful additions to fs@uwasa.fi so they may be
  18.  *  included in later releases.
  19.  *
  20.  *  This file should be edited with 4-column tabs!  (:set ts=4 sw=4 in vi)
  21.  */
  22.  
  23. #include <stdio.h>
  24. #include <math.h>
  25. #include "plot.h"
  26. #include "fchart.h"
  27.     
  28. struct label_def *first_label = NULL;
  29. struct linearrow_def *first_arrow = NULL;
  30.  
  31. extern char *strcpy(),*strcat();
  32. extern int strlen();
  33.  
  34. /* input data, parsing variables */
  35. extern struct lexical_unit token[];
  36. extern char input_line[];
  37. extern int num_tokens, c_token;
  38.  
  39. extern double real();
  40.  
  41. /******** Local functions ********/
  42. static int assign_label_tag();
  43. static int assign_arrow_tag();
  44. static void delete_label();
  45. static void delete_arrow();
  46.  
  47. /* not static: used by fcmd.c */
  48. void show_labels(), show_arrow();        
  49. void set_label();
  50. void set_nolabel();
  51. void set_arrow();
  52. void set_noarrow();
  53.  
  54. /* process a 'set label' command */
  55. /* set label {tag} {label_text} {at {page|picture} x,y} {pos} {height h} {width w} */
  56. void
  57. set_label()
  58. {
  59.     struct label_def *this_label = NULL;
  60.     struct label_def *new_label = NULL;
  61.     struct label_def *prev_label = NULL;
  62.     double x, y, h, w, a;
  63.     char text[MAX_LINE_LEN+1];
  64.     enum JUSTIFY just = LEFT;
  65.     enum LAB_ROT rot;
  66.     int tag;
  67.     BOOLEAN set_text, set_position, set_just=FALSE, set_h, set_w, set_r;
  68.     BOOLEAN page_label;
  69.     
  70.     /* get tag */
  71.     if (!END_OF_COMMAND && isnumber(c_token)) {
  72.         tag = (int)real(c_token);
  73.         if (tag == 0)
  74.             int_error("tag must be > zero", c_token);
  75.         c_token++;
  76.     } else
  77.         tag = assign_label_tag(); /* default next tag */
  78.     
  79.     /* get text */
  80.     if (!END_OF_COMMAND && isstring(c_token)) {
  81.         quote_str(text, c_token);
  82.         c_token++;
  83.         set_text = TRUE;
  84.     } else {
  85.         text[0] = '\0';        /* default no text */
  86.         set_text = FALSE;
  87.     }
  88.         
  89.     /* get justification -- why not here ? */
  90.     if (!END_OF_COMMAND) {
  91.         if (almost_equals(c_token,"l$eft")) {
  92.             just = LEFT;
  93.             set_just = TRUE;
  94.             c_token++;
  95.         }
  96.         else if (almost_equals(c_token,"c$entre")
  97.                  || almost_equals(c_token,"c$enter")) {
  98.             just = CENTRE;
  99.             set_just = TRUE;
  100.             c_token++;
  101.         }
  102.         else if (almost_equals(c_token,"ri$ght")) {
  103.             just = RIGHT;
  104.             set_just = TRUE;
  105.             c_token++;
  106.         }
  107.     }
  108.  
  109.     /* get position */
  110.     if (!END_OF_COMMAND && equals(c_token, "at")) {
  111.         c_token++;
  112.         if (END_OF_COMMAND)
  113.             int_error("coordinates expected", c_token);
  114.         if (almost_equals(c_token, "pa$ge")) {
  115.             c_token++;
  116.             page_label = TRUE;
  117.         }
  118.         else if (almost_equals(c_token, "pi$cture")) {
  119.             c_token++;
  120.             page_label = FALSE;
  121.         }
  122.         else if (!isnumber(c_token))
  123.             int_error("'page' or 'picture' expected", c_token);
  124.         else
  125.             page_label = FALSE;
  126.         x = real(c_token++);
  127.         if (!equals(c_token,","))
  128.             int_error("',' expected", c_token);
  129.         else
  130.             c_token++;
  131.         y = real(c_token++);
  132.         set_position = TRUE;
  133.     } else {
  134.         x = y = 0;            /* default at origin */
  135.         page_label = FALSE;
  136.         set_position = FALSE;
  137.     }
  138.     
  139.     /* get justification */
  140.     if (!END_OF_COMMAND) {
  141.         if (almost_equals(c_token,"l$eft")) {
  142.             if (set_just)
  143.                 int_error("only one justification is allowed", c_token);
  144.             just = LEFT;
  145.             set_just = TRUE;
  146.             c_token++;
  147.         }
  148.         else if (almost_equals(c_token,"c$entre")
  149.                  || almost_equals(c_token,"c$enter")) {
  150.             if (set_just)
  151.                 int_error("only one justification is allowed", c_token);
  152.             just = CENTRE;
  153.             set_just = TRUE;
  154.             c_token++;
  155.         }
  156.         else if (almost_equals(c_token,"ri$ght")) {
  157.             if (set_just)
  158.                 int_error("only one justification is allowed", c_token);
  159.             just = RIGHT;
  160.             set_just = TRUE;
  161.             c_token++;
  162.         }
  163.     }
  164.  
  165.     /* get height */
  166.     if (!END_OF_COMMAND && almost_equals(c_token, "he$ight")) {
  167.         c_token++;
  168.         h = real(c_token++);
  169.         set_h = TRUE;
  170.     }
  171.     else {
  172.         h = 0.0;
  173.         set_h = FALSE;
  174.     }
  175.  
  176.     /* get width */
  177.     if (!END_OF_COMMAND && almost_equals(c_token, "wi$dth")) {
  178.         c_token++;
  179.         w = real(c_token++);
  180.         set_w = TRUE;
  181.     }
  182.     else {
  183.         w = 0.0;
  184.         set_w = FALSE;
  185.     }
  186.  
  187.     /* get angle */
  188.     if (!END_OF_COMMAND && almost_equals(c_token, "ro$tation")) {
  189.         int sign = 1;
  190.         c_token++;
  191.         if (equals(c_token, "-")) {
  192.             c_token++;
  193.             sign = -1;
  194.         }
  195.         a = (double)sign * real(c_token++);
  196.         rot = L_RANDOM;
  197.         set_r = TRUE;
  198.     }
  199.     else if (!END_OF_COMMAND) {
  200.         if (almost_equals(c_token, "di$rection")) {
  201.             c_token++;
  202.             set_r = TRUE;        /* empty direction defaults to normal */
  203.         }
  204.         else
  205.             set_r = FALSE;
  206.         if (!END_OF_COMMAND && (almost_equals(c_token, "n$orth") ||
  207.             almost_equals(c_token, "v$ertical") || almost_equals(c_token, "u$p"))) {
  208.             c_token++;
  209.             rot = L_BOTTOM;
  210.             set_r = TRUE;
  211.         }
  212.         else if (!END_OF_COMMAND && (almost_equals(c_token, "s$outh") ||
  213.                  almost_equals(c_token, "do$wn"))) {
  214.             c_token++;
  215.             rot = L_TOP;
  216.             set_r = TRUE;
  217.         }
  218.         else if (!END_OF_COMMAND && (almost_equals(c_token, "we$st") ||
  219.                  almost_equals(c_token, "l$eft"))) {
  220.             c_token++;
  221.             rot = L_UPSIDE;
  222.             set_r = TRUE;
  223.         }
  224.         else if (!END_OF_COMMAND && (almost_equals(c_token, "ho$rizontal") ||
  225.                  almost_equals(c_token, "e$ast") || almost_equals(c_token, "ri$ght"))) {
  226.             c_token++;
  227.             rot = L_NORMAL;
  228.             set_r = TRUE;
  229.         }
  230.         else {
  231.             rot = L_NORMAL;
  232.         }
  233.     }
  234.     else {
  235.         rot = L_NORMAL;
  236.         set_r = FALSE;
  237.     }
  238.         
  239.     if (!END_OF_COMMAND)
  240.         int_error("extraneous or out-of-order arguments in set label", c_token);
  241.     
  242.     /* OK! add label */
  243.     if (first_label != NULL) { /* skip to last label */
  244.         for (this_label = first_label; this_label != NULL ; 
  245.              prev_label = this_label, this_label = this_label->next)
  246.             /* is this the label we want? */
  247.             if (tag <= this_label->tag)
  248.                 break;
  249.     }
  250.     if (this_label != NULL && tag == this_label->tag) {
  251.         /* changing the label */
  252.         if (set_position) {
  253.             this_label->x = x;
  254.             this_label->y = y;
  255.             this_label->paged = page_label;
  256.         }
  257.         if (set_text)
  258.             (void) strcpy(this_label->text, text);
  259.         if (set_just)
  260.             this_label->pos = just;
  261.         if (set_h)
  262.             this_label->h = h;
  263.         if (set_w)
  264.             this_label->w = w;
  265.         if (set_r) {
  266.             this_label->rot = rot;
  267.             this_label->a = a;
  268.         }
  269.     } else {
  270.         /* adding the label */
  271.         new_label = (struct label_def *) 
  272.             alloc ( (unsigned int) sizeof(struct label_def), "label");
  273.         if (prev_label != NULL)
  274.             prev_label->next = new_label; /* add it to end of list */
  275.         else 
  276.             first_label = new_label; /* make it start of list */
  277.         new_label->tag = tag;
  278.         new_label->next = this_label;
  279.         new_label->x = x;
  280.         new_label->y = y;
  281.         (void) strcpy(new_label->text, text);
  282.         new_label->pos = just;
  283.         new_label->h = h;
  284.         new_label->w = w;
  285.         new_label->rot = rot;
  286.         new_label->a = a;
  287.         new_label->paged = page_label;
  288.     }
  289. }
  290.  
  291. /* process 'set nolabel' command */
  292. /* set nolabel {tag} */
  293. void
  294. set_nolabel()
  295. {
  296.     struct label_def *this_label;
  297.     struct label_def *prev_label; 
  298.     int tag;
  299.     
  300.     if (END_OF_COMMAND) {        /* delete all labels */
  301.         while (first_label != NULL)
  302.             delete_label((struct label_def *)NULL, first_label);
  303.     }
  304.     else {
  305.         tag = (int)real(c_token++);
  306.         if (!END_OF_COMMAND)
  307.             int_error("extraneous arguments to set nolabel", c_token);
  308.         for (this_label = first_label, prev_label = NULL;
  309.              this_label != NULL;
  310.              prev_label = this_label, this_label = this_label->next) {
  311.             if (this_label->tag == tag) {
  312.                 delete_label(prev_label, this_label);
  313.                 return;        /* exit, our job is done */
  314.             }
  315.         }
  316.         int_error("label not found", c_token);
  317.     }
  318. }
  319.  
  320. /* assign a new label tag */
  321. /* labels are kept sorted by tag number, so this is easy */
  322. static int                /* the lowest unassigned tag number */
  323. assign_label_tag()
  324. {
  325.     struct label_def *this_label;
  326.     int last = 0;            /* previous tag value */
  327.     
  328.     for (this_label = first_label; this_label != NULL;
  329.          this_label = this_label->next)
  330.         if (this_label->tag == last+1)
  331.             last++;
  332.         else
  333.             break;
  334.     
  335.     return (last+1);
  336. }
  337.  
  338. /* delete label from linked list started by first_label.
  339.  * called with pointers to the previous label (prev) and the 
  340.  * label to delete (this).
  341.  * If there is no previous label (the label to delete is
  342.  * first_label) then call with prev = NULL.
  343.  */
  344. static void
  345. delete_label(prev,this)
  346. struct label_def *prev, *this;
  347. {
  348.     if (this!=NULL)    {        /* there really is something to delete */
  349.         if (prev!=NULL)        /* there is a previous label */
  350.             prev->next = this->next; 
  351.         else                /* this = first_label so change first_label */
  352.             first_label = this->next;
  353.         free((char *)this);
  354.     }
  355. }
  356.  
  357.  
  358. /* process a 'set arrow' and 'set line' command */
  359. /* set arrow|line {tag} {from { {page|picture} x,y} {to {page|picture} x,y} */
  360. void
  361. set_arrow(arrow)
  362. BOOLEAN arrow;
  363. {
  364.     struct linearrow_def *this_arrow = NULL;
  365.     struct linearrow_def *new_arrow = NULL;
  366.     struct linearrow_def *prev_arrow = NULL;
  367.     double sx, sy;
  368.     double ex, ey;
  369.     int tag;
  370.     BOOLEAN set_start, set_end;
  371.     BOOLEAN sp, ep;
  372.     
  373.     /* get tag */
  374.     if (!END_OF_COMMAND && isnumber(c_token)) {
  375.         tag = (int)real(c_token++);
  376.         if (tag == 0)
  377.             int_error("tag must be > zero", c_token);
  378.     } else
  379.         tag = assign_arrow_tag(); /* default next tag */
  380.     
  381.     /* get start position */
  382.     if (!END_OF_COMMAND && almost_equals(c_token, "f$rom")) {
  383.         c_token++;
  384.         if (END_OF_COMMAND)
  385.             int_error("start coordinates expected", c_token);
  386.         else if (almost_equals(c_token, "pa$ge")) {
  387.             c_token++;
  388.             sp = TRUE;
  389.         }
  390.         else if (almost_equals(c_token, "pi$cture")) {
  391.             c_token++;
  392.             sp = FALSE;
  393.         }
  394.         else
  395.             sp = FALSE;
  396.  
  397.         sx = real(c_token++);
  398.         if (!equals(c_token,","))
  399.             int_error("',' expected",c_token);
  400.         c_token++;
  401.         sy = real(c_token++);
  402.         set_start = TRUE;
  403.     } else {
  404.         sx = sy = 0;            /* default at origin */
  405.         sp = FALSE;
  406.         set_start = FALSE;
  407.     }
  408.     
  409.     /* get end position */
  410.     if (!END_OF_COMMAND && almost_equals(c_token, "t$o")) {
  411.         c_token++;
  412.         if (END_OF_COMMAND)
  413.             int_error("end coordinates expected", c_token);
  414.         else if (almost_equals(c_token, "pa$ge")) {
  415.             c_token++;
  416.             ep = TRUE;
  417.         }
  418.         else if (almost_equals(c_token, "pi$cture")) {
  419.             c_token++;
  420.             ep = FALSE;
  421.         }
  422.         else
  423.             ep = FALSE;
  424.  
  425.         ex = real(c_token++);
  426.         if (!equals(c_token,","))
  427.             int_error("',' expected",c_token);
  428.         c_token++;
  429.         ey = real(c_token++);
  430.         set_end = TRUE;
  431.     } else {
  432.         ex = ey = 0;            /* default at origin */
  433.         ep = FALSE;
  434.         set_end = FALSE;
  435.     }
  436.     
  437.     /* get start position - what the heck, either order is ok */
  438.     if (!END_OF_COMMAND && almost_equals(c_token, "f$rom")) {
  439.         if (set_start)
  440.             int_error("only one 'from' is allowed", c_token);
  441.         c_token++;
  442.         if (END_OF_COMMAND)
  443.             int_error("start coordinates expected", c_token);
  444.         else if (almost_equals(c_token, "pa$ge")) {
  445.             c_token++;
  446.             sp = TRUE;
  447.         }
  448.         else if (almost_equals(c_token, "pi$cture")) {
  449.             c_token++;
  450.             sp = FALSE;
  451.         }
  452.         else
  453.             sp = FALSE;
  454.  
  455.         sx = real(c_token++);
  456.         if (!equals(c_token,","))
  457.             int_error("',' expected",c_token);
  458.         c_token++;
  459.         sy = real(c_token++);
  460.         set_start = TRUE;
  461.     }
  462.     
  463.     if (!END_OF_COMMAND)
  464.         int_error("extraneous or out-of-order arguments in set arrow/line", c_token);
  465.     
  466.     /* OK! add arrow */
  467.     if (first_arrow != NULL) { /* skip to last arrow */
  468.         for (this_arrow = first_arrow; this_arrow != NULL ; 
  469.              prev_arrow = this_arrow, this_arrow = this_arrow->next)
  470.             /* is this the arrow we want? */
  471.             if (tag <= this_arrow->tag)
  472.                 break;
  473.     }
  474.     if (this_arrow != NULL && tag == this_arrow->tag) {
  475.         /* changing the arrow */
  476.         if (set_start) {
  477.             this_arrow->sx = sx;
  478.             this_arrow->sy = sy;
  479.             this_arrow->startp = sp;
  480.         }
  481.         if (set_end) {
  482.             this_arrow->ex = ex;
  483.             this_arrow->ey = ey;
  484.             this_arrow->endp = ep;
  485.         }
  486.         this_arrow->arrow = arrow;
  487.     } else {
  488.         /* adding the arrow */
  489.         new_arrow = (struct linearrow_def *) 
  490.             alloc ( (unsigned int) sizeof(struct linearrow_def), "arrow");
  491.         if (prev_arrow != NULL)
  492.             prev_arrow->next = new_arrow; /* add it to end of list */
  493.         else 
  494.             first_arrow = new_arrow; /* make it start of list */
  495.         new_arrow->tag = tag;
  496.         new_arrow->next = this_arrow;
  497.         new_arrow->sx = sx;
  498.         new_arrow->sy = sy;
  499.         new_arrow->startp = sp;
  500.         new_arrow->ex = ex;
  501.         new_arrow->ey = ey;
  502.         new_arrow->endp = ep;
  503.         new_arrow->arrow = arrow;
  504.     }
  505. }
  506.  
  507. /* process 'set noarrow' and 'set noline' command */
  508. /* set noarrow {tag} */
  509. void
  510. set_noarrow()
  511. {
  512.     struct linearrow_def *this_arrow;
  513.     struct linearrow_def *prev_arrow; 
  514.     int tag;
  515.     
  516.     if (END_OF_COMMAND) {
  517.         /* delete all arrows */
  518.         while (first_arrow != NULL)
  519.             delete_arrow((struct linearrow_def *)NULL,first_arrow);
  520.     }
  521.     else {
  522.         /* get tag */
  523.         tag = (int)real(c_token++);
  524.         if (!END_OF_COMMAND)
  525.             int_error("extraneous arguments to set noarrow/noline", c_token);
  526.         for (this_arrow = first_arrow, prev_arrow = NULL;
  527.              this_arrow != NULL;
  528.              prev_arrow = this_arrow, this_arrow = this_arrow->next) {
  529.             if (this_arrow->tag == tag) {
  530.                 delete_arrow(prev_arrow, this_arrow);
  531.                 return;        /* exit, our job is done */
  532.             }
  533.         }
  534.         int_error("arrow/line not found", c_token);
  535.     }
  536. }
  537.  
  538. /* assign a new arrow tag */
  539. /* arrows are kept sorted by tag number, so this is easy */
  540. static int                /* the lowest unassigned tag number */
  541. assign_arrow_tag()
  542. {
  543.     struct linearrow_def *this_arrow;
  544.     int last = 0;            /* previous tag value */
  545.     
  546.     for (this_arrow = first_arrow; this_arrow != NULL;
  547.          this_arrow = this_arrow->next)
  548.         if (this_arrow->tag == last+1)
  549.             last++;
  550.         else
  551.             break;
  552.     
  553.     return (last+1);
  554. }
  555.  
  556. /* delete arrow from linked list started by first_arrow.
  557.  * called with pointers to the previous arrow (prev) and the 
  558.  * arrow to delete (this).
  559.  * If there is no previous arrow (the arrow to delete is
  560.  * first_arrow) then call with prev = NULL.
  561.  */
  562. static void
  563. delete_arrow(prev,this)
  564. struct linearrow_def *prev, *this;
  565. {
  566.     if (this!=NULL)    {        /* there really is something to delete */
  567.         if (prev!=NULL)        /* there is a previous arrow */
  568.             prev->next = this->next; 
  569.         else                /* this = first_arrow so change first_arrow */
  570.             first_arrow = this->next;
  571.         free((char *)this);
  572.     }
  573. }
  574.  
  575. void
  576. show_labels(tag, fp, save)
  577. int tag;                /* 0 means show all */
  578. FILE *fp;
  579. BOOLEAN save;
  580. {
  581.     struct label_def *this_label;
  582.     BOOLEAN showed = FALSE;
  583.     
  584.     for (this_label = first_label; this_label != NULL;
  585.          this_label = this_label->next) {
  586.         if (tag == 0 || tag == this_label->tag) {
  587.             showed = TRUE;
  588.             fprintf(fp,"%slabel %d \"%s\" %s at %s %lg,%lg",
  589.                     save ? "set " : "\t",
  590.                     this_label->tag, this_label->text,
  591.                     (this_label->pos==LEFT ? "left" : (this_label->pos==RIGHT ? "right" : "centre")),
  592.                     this_label->paged ? "page" : "picture",
  593.                     this_label->x, this_label->y);
  594.             if (this_label->h != 0.0)
  595.                 fprintf(fp, " height %lg", this_label->h);
  596.             if (this_label->w != 0.0)
  597.                 fprintf(fp, " width %lg", this_label->w);
  598.             switch(this_label->rot) {
  599.                 case L_NORMAL: {
  600.                     break;
  601.                 }
  602.                 case L_UPSIDE: {
  603.                     fprintf(fp, " direction left");
  604.                     break;
  605.                 }
  606.                 case L_BOTTOM: {
  607.                     fprintf(fp, " vertical");
  608.                     break;
  609.                 }
  610.                 case L_TOP: {
  611.                     fprintf(fp, " direction down");
  612.                     break;
  613.                 }
  614.                 case L_RANDOM: {
  615.                     fprintf(fp, " rotation %lg", this_label->a);
  616.                     break;
  617.                 }
  618.             }
  619.             fputc('\n',fp);
  620.         }
  621.     }
  622.     if (tag > 0 && !showed)
  623.         int_error("label not found", c_token);
  624. }
  625.  
  626. void
  627. show_arrow(tag, fp, save)
  628. int tag;                /* 0 means show all */
  629. FILE *fp;
  630. BOOLEAN save;
  631. {
  632.     struct linearrow_def *this_arrow;
  633.     BOOLEAN showed = FALSE;
  634.     
  635.     for (this_arrow = first_arrow; this_arrow != NULL;
  636.          this_arrow = this_arrow->next) {
  637.         if (tag == 0 || tag == this_arrow->tag) {
  638.             showed = TRUE;
  639.             fprintf(fp,"%s%s %d from %s %lg,%lg to %s %lg,%lg\n",
  640.                     save ? "set " : "\t",
  641.                     this_arrow->arrow ? "arrow" : "line",
  642.                     this_arrow->tag,
  643.                     this_arrow->startp ? "page" : "picture",
  644.                     this_arrow->sx, this_arrow->sy,
  645.                     this_arrow->endp ? "page" : "picture",
  646.                     this_arrow->ex, this_arrow->ey);
  647.         }
  648.     }
  649.     if (tag > 0 && !showed)
  650.         int_error("arrow not found", c_token);
  651. }
  652.  
  653.  
  654.  
  655.  
  656.  
  657.  
  658.  
  659.  
  660.  
  661.